package com.api.pay.controller;

import cn.hutool.core.codec.Base64;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.api.apicommon.model.entity.User;
import com.api.apicommon.response.BaseResponse;
import com.api.apicommon.response.ErrorCode;
import com.api.apicommon.response.ResultUtils;
import com.api.apicommon.server.InnerInterfaceUserInfo;
import com.api.pay.config.ApiPayConfig;
import com.api.pay.model.domain.ApiOrder;
import com.api.pay.model.dto.order.OrderDto;
import com.api.pay.service.ApiGoodsService;
import com.api.pay.service.ApiOrderService;
import com.api.pay.util.AliPayUtil;
import com.api.pay.util.PayConstant;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import static com.alipay.api.AlipayConstants.CHARSET;

@RestController
@Slf4j
public class OrderController {
    public static final String USER_LOGIN_STATE = "userLoginState";
    @Autowired
    private ApiOrderService apiOrderService;
    @Autowired
    private ApiGoodsService apiGoodsService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private AliPayUtil aliPayUtil;
    @DubboReference
    private InnerInterfaceUserInfo innerInterfaceUserInfo;
    @Autowired
    private ApiPayConfig apiPayConfig;

    /**
     * 查看用户所有订单
     *
     * @param request
     * @return
     */
    @GetMapping("/query/list")
    public BaseResponse<List<ApiOrder>> queryByUserId(HttpServletRequest request) {
        User currentUser = (User) request.getSession().getAttribute(USER_LOGIN_STATE);
        Long userId = currentUser.getId();
        return apiOrderService.queryOrderById(userId);
    }

    /**
     * 前端轮询查看订单状态
     */
    @GetMapping("/query/one")
    public BaseResponse queryByOrder(Long id) {
        QueryWrapper<ApiOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", id);
        ApiOrder order = apiOrderService.getOne(queryWrapper);
        if (order == null) {
            return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR);
        }
        String status = apiOrderService.queryOrderStatus(order);

        return ResultUtils.success(status);
    }

    /**
     * 下单
     *
     * @param orderDto
     * @param request
     * @return
     */
    @PutMapping("/order")
    public BaseResponse GenerateOrders(@RequestBody OrderDto orderDto, HttpServletRequest request) throws AlipayApiException {
        Object session = request.getSession().getAttribute(USER_LOGIN_STATE);
        User user = (User) session;
        if (user == null) {
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR);
        }
        String encode = Base64.encode(orderDto.getGoodsId() + orderDto.getCount().toString() + user.getId().toString());
        //订单幂等处理
        if (!orderDto.isRepeatCommit()) {
            if (Boolean.FALSE.equals(stringRedisTemplate.opsForValue().setIfAbsent("order" + encode, "1", 60 * 5, java.util.concurrent.TimeUnit.SECONDS))) {
                return ResultUtils.error(ErrorCode.REPEATE_COMMIT_ERROR);
            }
        }
        return apiOrderService.order(orderDto, user.getId());
    }

    /**
     * 取消订单
     *
     * @param orderSn 订单编号
     * @param request
     * @return
     */
    @PutMapping("/order/cancel")
    public BaseResponse cancelOrder(Long orderSn, HttpServletRequest request) {
        Object sessionAttribute = request.getSession().getAttribute(USER_LOGIN_STATE);
        User user = (User) sessionAttribute;
        if (user == null) {
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR);
        }
        QueryWrapper<ApiOrder> apiOrderQueryWrapper = new QueryWrapper<>();
        apiOrderQueryWrapper.eq("orderSn", orderSn);
        ApiOrder apiOrder = apiOrderService.getOne(apiOrderQueryWrapper);
        try {
            AlipayTradeQueryResponse alipayTradeQueryResponse = aliPayUtil.queryOrder(apiOrder);
            if (!"WAIT_BUYER_PAY".equals(alipayTradeQueryResponse.getTradeStatus())|| !"10000".equals(alipayTradeQueryResponse.getCode())) {
                return new BaseResponse(30001, "订单状态异常");
            }
        } catch (AlipayApiException e) {
            return new BaseResponse(20001, e.getErrMsg());
        }
        try {
            if (!aliPayUtil.closeOrder(apiOrder)) {
                return ResultUtils.error(ErrorCode.OPERATION_ERROR);
            }
        } catch (AlipayApiException e) {
            return new BaseResponse(30001, e.getErrMsg());
        }
        UpdateWrapper<ApiOrder> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("status", PayConstant.TRADE_CLOSED).eq("status", PayConstant.TRADE_NO_PAY).eq("orderSn", orderSn);
        if (!apiOrderService.update(updateWrapper)) {
            return ResultUtils.error(ErrorCode.OPERATION_ERROR);
        }
        return ResultUtils.success("操作成功");
    }

    /**
     * 支付订单
     *
     * @param orderSn 订单编号
     * @param request
     * @return
     */
    @GetMapping("/order/pay")
    public BaseResponse payOrder(Long orderSn, HttpServletRequest request) {
        Object sessionAttribute = request.getSession().getAttribute(USER_LOGIN_STATE);
        User user = (User) sessionAttribute;
        if (user == null) {
            return ResultUtils.error(ErrorCode.NOT_LOGIN_ERROR);
        }
        QueryWrapper<ApiOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("orderSn", orderSn).eq("status", PayConstant.TRADE_NO_PAY);
        ApiOrder apiOrder = apiOrderService.getOne(queryWrapper);
        if (apiOrder == null) {
            return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR);
        }
        try {
            AlipayTradeQueryResponse response = aliPayUtil.queryOrder(apiOrder);
            if (!"WAIT_BUYER_PAY".equals(response.getTradeStatus())|| !"10000".equals(response.getCode())) {
                return new BaseResponse(30001, "订单状态异常");
            }
        } catch (AlipayApiException e) {
            return ResultUtils.success(e.getErrMsg());
        }

        return ResultUtils.success(apiOrder.getQrCode());
    }

    /**
     * TODO 后续改成支付成功,更新数据库订单状态,发送消息队列,监听队列,修改数据库用户接口调用次数
     * 支付宝支付成功回调接口
     *
     * @param request
     * @return
     */
    @PostMapping("/order/callback")
    public String callback(HttpServletRequest request) throws AlipayApiException {
        //获取支付宝POST过来反馈信息，将异步通知中收到的待验证所有参数都存放到map中
        Map<String, String> params = new HashMap<String, String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用。
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        //调用SDK验证签名
        //公钥验签示例代码
        boolean signVerified = AlipaySignature.rsaCheckV1(params, apiPayConfig.getPublicKey(), CHARSET, apiPayConfig.getSignType());
        //公钥证书验签示例代码
        boolean flag = AlipaySignature.rsaCertCheckV1(params, "cert/appCertPublicKey_2021004152613293.crt", "UTF-8", "RSA2");

        if (signVerified) {
            // TODO 验签成功后
            //按照支付结果异步通知中的描述，对支付结果中的业务内容进行1\2\3\4二次校验，校验成功后在response中返回success
        } else {
            // TODO 验签失败则记录异常日志，并在response中返回fail.
        }
        return "success";
    }
       
}
